(function () {
    /* function fn(a: any): any {
        return a;
    } */


    /*
        在定义函数或类时，如果遇到类型不明确的情况
        我们不建议使用any，建议使用泛型来定义不确定的类型
    */
    // <T> 相当于表示定义了一个 T 类型的泛型，此时 a 的类型就是T,当a调用时是什么类型T就为什么类型
    function fn<T>(a: T): T {
        return a;

    }

    // 可以直接调用具有泛型的函数
    let result1 = fn(10);  // 不指定泛型：用到了TS的类型自动推断
    // <string> 设置泛型的类型为string
    let result2 = fn<string>("hello");  // 直接指定泛型类型


    // 泛型可以同时指定多个
    function fn2<M, N>(a: M, b: N): M {
        console.log(a, b)
        return a;
    }

    let result3 = fn2<string, number>("路飞", 18);


    // 创建Inter接口
    interface Inter {
        length: number;
    }
    // 指定fn3中泛型T继承至Inter接口，实现Inter接口（泛型T必须是Inter的实现类即子类）
    function fn3<T extends Inter>(a: T): number {
        return a.length;  // 返回值规定了类型为number，且属性中必须有 .length方法
    }
    fn3("123");  // 成功 字符串具有 .length 方法
    // fn3(123);  // 报错 类型“number”的参数不能赋给类型“Inter”的参数
    // fn3({ name: "hello" });  //报错 类型“{ name: string; }”的参数不能赋给类型“Inter”的参数。对象文字可以只指定已知属性，并且“name”不在类型“Inter”中
    fn3({ length: 10 });  // 成功 因为Inter中有length属性且类型为number



    // 
    class MyClass<T> {
        name: T;
        constructor(name: T) {
            this.name = name
        }

    }

    // const myClass = new MyClass("路飞");
    const myClass = new MyClass<string>("路飞");

})()